import socket
import fcntl                            # only available in unix
import struct
import array
from ma.const import *

intf_name_size_max = 32
max_no_interfaces = 128

def get_network_interfaces():
    """Get all the network interfaces on the current node
    
    A usual response will be a list containing the loop-
    back address and the ethernet interface ['lo', 'eth0']
    
    """
    bytes = max_no_interfaces * intf_name_size_max
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    names = array.array('B', [0] * bytes)
    outbytes = struct.unpack('iL', fcntl.ioctl(
        s.fileno(),
        0x8912,  # SIOCGIFCONF
        struct.pack('iL', bytes, names.buffer_info()[0])
    ))[0]
    namestr = names.tostring()
    
    return [str(namestr[i:i+intf_name_size_max], encoding='utf8', errors='replace').split('\0', 1)[0] for i in range(0, outbytes, intf_name_size_max)]


def get_ip_address(interface_name):
    """Get the ip address associated with the interce name given
    
    Giving 'eth0' will give the IP associated with the ethernet
    interface. 'lo' will give you the loopback IP address.
    
    """ 
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', interface_name[:intf_name_size_max])
    )[20:24])


def get_ip_assoc_to_hostname():
    """Get the ip address which is associated to the node's name"""
    return socket.gethostbyname(socket.gethostname())


if __name__ == '__main__':
    #main for testing
    print("Communication Interface: ", XmlData.get_str_data(xml_network_interface))
    print("Communication Interface IP: ", get_ip_address(XmlData.get_str_data(xml_network_interface)))
    
    print("Loopback IP:", get_ip_address('lo'))
    print("IP associated with node name:", get_ip_assoc_to_hostname())
    print("Up network interfaces:", get_network_interfaces())
    